const child_process = require('child_process')

const fs = require('@/utils/fs_promise.js')
const stat = require('@/store/statistics.js')

let routes = []

async function ln_stat(repo, argv) {
    var [err, ret] = await to(fs.lstat(argv[1]))
    if (err) {
        return {
            flag: ERROR.NO_ENTRY,
            message: err,
        }
    }

    if (ret.isSymbolicLink() === false) {
        return {
            flag: ERROR.CONFLICT,
            message: 'invalid link file',
        }
    }

    var [err, ret] = await to(fs.readlink(argv[1]))
    if (err) {
        console.error(err)
        return {
            flag: ERROR.FAILURE,
            message: err,
        }
    }

    if (ret !== `${repo.path}/${argv[0]}`) {
        return {
            flag: ERROR.CONFLICT,
            message: 'invalid target file',
        }
    }

    return {
        flag: ERROR.OK,
        message: 'ok',
    }
}

async function ln_exec(repo, argv) {
    var [err, ret] = await to(ln_stat(repo, argv))
    if (ret.flag === ERROR.NO_ENTRY) {
        let ret = child_process.spawnSync('ln', ['-s', `${repo.path}/${argv[0]}`, argv[1]], {
            cwd: repo.path,
            stdio: ['ignore', 'inherit', 'inherit'],
        })
        ret.flag = ret
    }
    return ret
}

routes.push({
    name: 'ln',
    argc: 2,
    stat: ln_stat,
    exec: ln_exec,
})

function ln_repo_stat(repo, argv) {
    return ln_stat(repo, ["", argv[0]])
}

function ln_repo_exec(repo, argv) {
    return ln_exec(repo, ["", argv[0]])
}

routes.push({
    name: 'ln_repo',
    argc: 1,
    stat: ln_repo_stat,
    exec: ln_repo_exec,
})

async function hook(repo, func) {
    for (let i = 0; i < repo.action.length;) {
        let have = false
        for (let route of routes) {
            if (route.name === repo.action[i]) {
                i++
                await func(route, repo.action.slice(i, i + route.argc))
                i += route.argc
                have = true
                break
            }
        }

        if (have === false) {
            console.error(`no such action ${repo.action[i]}`)
            process.exit(1)
        }
    }
}

module.exports = {
    async stat(repo) {
        await hook(repo, async (route, argv) => {
            let [err, {flag, message}] = await to(route.stat(repo, argv))
            stat.append({
                flag,
                command: route.name,
                reponame: repo.name,
                target: argv[argv.length - 1],
                message,
            })
        })
    },
    async exec(repo) {
        await hook(repo, async (route, argv) => {
            let [err, {flag, message}] = await to(route.exec(repo, argv))
            stat.append({
                flag,
                command: route.name,
                reponame: repo.name,
                target: argv[argv.length - 1],
                message,
            })
        })
    },
}
